package com.xqboss.apps.controller.hama;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xqboss.apps.constant.Config;
import com.xqboss.apps.constant.RedisKey;
import com.xqboss.apps.domain.hama.*;
import com.xqboss.apps.dto.PageDto;
import com.xqboss.apps.dto.hama.SportMyTeamDto;
import com.xqboss.apps.service.consumer.ConsumerRealNameService;
import com.xqboss.apps.service.hama.HamaUserMixService;
import com.xqboss.apps.vo.hama.*;
import com.xqboss.common.annotation.Anonymous;
import com.xqboss.common.annotation.RepeatSubmit;
import com.xqboss.common.core.controller.BaseController;
import com.xqboss.common.core.domain.PageResult;
import com.xqboss.common.core.domain.R;
import com.xqboss.common.core.domain.entity.SysUser;
import com.xqboss.common.core.domain.model.LoginUser;
import com.xqboss.common.core.redis.lock.RedisLockUtils;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.StringUtils;
import com.xqboss.system.service.ISysConfigService;
import com.xqboss.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
 * <p>
 * 运动场 - APP
 * </p>
 *
 * @author 木鱼
 * @since 2024-02-28
 */
@RestController
@Slf4j
@Validated
@Api(tags = "运动场")
@RequestMapping("/apps/sport")
@RequiredArgsConstructor
public class HamaUserMixController extends BaseController {

    private final HamaUserMixService hamaUserMixService;//用户装备的加油手环

    private final ConsumerRealNameService consumerRealNameService;//用户实名信息

    private final ISysConfigService sysConfigService;//系统配置参数

    private final ISysUserService sysUserService;//用户信息

    private final RedisLockUtils redisLockUtils;//分布式锁

    @GetMapping("/mix")
    @ApiOperation(value = "运动场首页个人信息", notes = "用户相关信息", httpMethod = "GET")
    public R<HamaUserMixVO> getMix() {
        HamaUserMixVO vo = this.hamaUserMixService.getHamaMix(getUserId());
        return R.ok(vo,"获取运动场首页个人信息成功~");
    }

    @GetMapping("/mix-list")
    @ApiOperation(value = "运动场首页-装备信息", notes = "装备信息", httpMethod = "GET")
    public PageResult<HamaUserMixInfoVO> getMixList(PageDto<HamaMixConfig> dto) {
        IPage<HamaUserMixInfoVO> vo = this.hamaUserMixService.getHamaMixList(getUserId(),dto);
        return PageResult.ok(vo,"获取运动场首页个人信息成功~");
    }

    @GetMapping("/trends/{number}/{nftId}")
    @RepeatSubmit(interval = 1000, justUrl = true)
    @ApiOperation(value = "运动场首页动态数据", notes = "运动场首页动态数据", httpMethod = "GET")
    public R<HamaUserMixInfoTrendsVO> getMixTrends(@PathVariable
                                             @ApiParam(value = "投放装备数量",readOnly = true)
                                             @NotNull(message = "投放装备数量不能为空~")
                                             @Min(value = 1,message = "至少投放一张装备~")
                                             Integer number,
                                         @PathVariable
                                             @ApiParam(value = "装备id",readOnly = true)
                                             @NotNull(message = "装备id不能为空~")
                                             Long nftId) {
        HamaUserMixInfoTrendsVO vo = this.hamaUserMixService.getMixTrends(number,getUserId(),nftId);
        return R.ok(vo,"获取运动场首页动态数据成功~");
    }

    @GetMapping("/log")
    @ApiOperation(value = "装备加油手环-使用记录", notes = "装备加油手环-使用记录", httpMethod = "GET")
    public PageResult<HamaMixLog> getMixLog(@Validated PageDto<HamaMixLog> dto) {
        IPage<HamaMixLog> page = this.hamaUserMixService.getHamaMixLog(dto.newPage(),getUserId());
        return PageResult.ok(page,"获取记录成功~");
    }

    @GetMapping("/employ/{number}/{nftId}")
    @RepeatSubmit(interval = 1500, justUrl = true)
    @ApiOperation(value = "投放装备", notes = "投放装备", httpMethod = "GET")
    public R<HamaUserMix> employNft(@PathVariable
                                    @ApiParam(value = "投放装备数量",readOnly = true)
                                    @NotNull(message = "投放装备数量不能为空~")
                                    @Min(value = 1,message = "至少投放一张装备~")
                                        Integer number,
                                    @PathVariable
                                    @ApiParam(value = "装备id",readOnly = true)
                                    @NotNull(message = "装备id不能为空~")
                                            Long nftId) {
        Long userId=getUserId();
        //1 验证是否在空投结算
        this.hamaUserMixService.verifyInAirdrop();
        //2 验证用户信息
        this.consumerRealNameService.requireRealName(userId);
        //3 验证手环一次性装备数量限制
        Integer maxNumber = this.sysConfigService.getValue(Config.Sys.Sport.一次性允许最大装备的数量);
        Assert.isFalse(number<1 || number>maxNumber,()->new ServiceException("一次性最高投放"+maxNumber+"张"));
        //4 装备加油手环
        String redisKey = RedisKey.SPORT_POOL_LOCK + userId;
        try {
            redisLockUtils.lock(redisKey,"1", 10,30,"请不要重复点击~");
            return hamaUserMixService.employNft(number,userId,nftId);
        } catch (ServiceException e) {
            log.error("[employNft]投放装备异常",e);
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("[employNft]投放装备异常",e);
            return R.fail("参数错误~");
        } finally {
            redisLockUtils.unLock(redisKey,"1");
        }
    }

    @GetMapping("/team")
    @ApiOperation(value = "我的队伍首页信息", notes = "我的队伍首页信息", httpMethod = "GET")
    public R<HamaHelpVO> teamHelp() {
        HamaHelpVO vo = this.hamaUserMixService.teamHelp(getUserId());
        return R.ok(vo,"我的队伍首页信息获取成功~");
    }

    @GetMapping("/team-mine")
    @ApiOperation(value = "我的队伍信息", notes = "我的队伍信息", httpMethod = "GET")
    public PageResult<HamaHelpMyUserVO> myTeam(@Validated SportMyTeamDto<HamaHelp> dto) {
        IPage<HamaHelpMyUserVO> page = this.hamaUserMixService.getMyTeam(dto,getUserId());
        return PageResult.ok(page,"我的队伍信息获取成功~");
    }

    @GetMapping("/team-create")
    @RepeatSubmit(interval = 1500, justUrl = true)
    @ApiOperation(value = "创建队伍", notes = "创建队伍", httpMethod = "GET")
    public R<String> createTeam() {
        LoginUser loginUser = getLoginUser();
        //1 验证是否在空投结算
        this.hamaUserMixService.verifyInAirdrop();
        //2 验证用户信息
        this.consumerRealNameService.requireRealName(loginUser.getUserId());
        //3 创建队伍
        String redisKey = RedisKey.SPORT_POOL_LOCK + loginUser.getUserId();
        try {
            redisLockUtils.lock(redisKey,"1", 10,30,"请不要重复点击~");
            return hamaUserMixService.createTeam(loginUser);
        } catch (ServiceException e) {
            log.error("[createTeam]创建队伍异常",e);
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("[createTeam]创建队伍异常",e);
            return R.fail("参数错误~");
        } finally {
            redisLockUtils.unLock(redisKey,"1");
        }
    }

    @GetMapping("/team-join")
    @Anonymous
    @RepeatSubmit(interval = 1500, justUrl = true)
    @ApiOperation(value = "加入队伍", notes = "加入队伍", httpMethod = "GET")
    public R<Object> joinTeam(@ApiParam("队长手机号")@RequestParam(value = "mobile", required = false)String mobile,
                              @ApiParam("队长用户id")@RequestParam(value = "parentUserId", required = false)Long parentUserId,
                              @ApiParam("被邀请人手机号")@RequestParam(value = "phoneNumber", required = false)String phoneNumber) {
        Long userId = ObjUtil.isEmpty(phoneNumber)?getUserId():null;//userId为空说明为：注册邀请
        if (userId==null && StringUtils.isEmpty(phoneNumber)) {
            return R.fail("参数错误：请传递被邀请人手机号~");
        }
        //1 验证是否在空投结算
        this.hamaUserMixService.verifyInAirdrop();
        //2 验证用户手机号
        if (StringUtils.isNotEmpty(mobile)){
            return R.fail("请输入队长用户id~");
        }
        //3 验证加入用户信息（队员），用户id为空（注册邀请），通过邀请人的用户id确定被邀请人的信息
        boolean isInvite = userId == null &&  StringUtils.isNotEmpty(phoneNumber);
        SysUser joinUser = isInvite?this.sysUserService.selectUserByUserName(phoneNumber):this.sysUserService.getUserInfoOrNull(userId);
        if (joinUser==null) {
            return R.fail("用户不存在~");
        }
        boolean isRealName = this.consumerRealNameService.getUserRealNameOrNull(userId)!=null;//加入队伍用户是否实名
        // 非邀请加入队伍，需要判断是否实名
        if (!isInvite && !isRealName) {
            return R.fail("请实名后加入队伍~");
        }
        //4 验证加入用户信息（队长）
        SysUser teamUser = null;
        parentUserId = ObjUtil.isEmpty(parentUserId) && isInvite?joinUser.getInviterId():parentUserId;
        if (parentUserId!=null) {
            teamUser = this.sysUserService.getUserInfoOrNull(parentUserId);
        }
        if (teamUser==null) {
            return R.fail("加入的队伍队长不存在~");
        }
        if (this.consumerRealNameService.getUserRealNameOrNull(teamUser.getUserId())==null) {
            return R.fail("加入的队伍队长未实名~");
        }
        //5 加入验证
        if(parentUserId!=null && joinUser.getUserId().longValue()==parentUserId.longValue()){
            return R.fail("不能自己加入自己队伍~");
        }
        //5 加入队伍
        String redisKey = RedisKey.SPORT_POOL_LOCK + joinUser.getUserId();
        try {
            redisLockUtils.lock(redisKey,"1", 10,30,"请不要重复点击~");
            return hamaUserMixService.joinTeam(teamUser,joinUser,isRealName);
        } catch (ServiceException e) {
            log.error("[joinTeam]加入队伍异常",e);
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("[joinTeam]加入队伍异常",e);
            return R.fail("参数错误~");
        } finally {
            redisLockUtils.unLock(redisKey,"1");
        }
    }

    @GetMapping("/sport-data")
    @ApiOperation(value = "运动场数据", notes = "运动场数据", httpMethod = "GET")
    public PageResult<HamaOpenConfigVO> sportDataConfig(@Validated PageDto<HamaOpenConfig> dto) {
        IPage<HamaOpenConfigVO> page = this.hamaUserMixService.sportDataConfig(dto.newPage());
        return PageResult.ok(page,"建设运动场数据获取成功~");
    }


    @GetMapping("/sport-mine")
    @ApiOperation(value = "我的运动场", notes = "我的运动场数据", httpMethod = "GET")
    public PageResult<HamaUserOpenVo> myBuildSport(@Validated PageDto<HamaUserOpen> dto) {
        IPage<HamaUserOpenVo> page = this.hamaUserMixService.myBuildSport(dto.newPage(),getUserId());
        return PageResult.ok(page,"我的运动场数据获取成功~");
    }

    @GetMapping("/sport-build")
    @RepeatSubmit(interval = 1500, justUrl = true)
    @ApiOperation(value = "建设运动场", notes = "用户建设运动场", httpMethod = "GET")
    public R<String> userBuildSport(@ApiParam("openId")@RequestParam(name = "openId")@NotNull(message = "运动场id不能为空~") Long openId) {
        Long userId=getUserId();
        //1 验证是否在空投结算
        this.hamaUserMixService.verifyInAirdrop();
        //2 验证用户信息
        this.consumerRealNameService.requireRealName(userId);
        //3 建设运动场
        String redisKey = RedisKey.SPORT_POOL_LOCK + userId;
        try {
            redisLockUtils.lock(redisKey,"1", 10,30,"请不要重复点击~");
            return hamaUserMixService.userBuildSport(userId,openId);
        } catch (ServiceException e) {
            log.error("[userBuildSport]建设运动场异常",e);
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("[userBuildSport]建设运动场异常",e);
            return R.fail("参数错误~");
        } finally {
            redisLockUtils.unLock(redisKey,"1");
        }
    }
}
